package com.bzyd.jpa.specification;

import com.bzyd.jpa.entity.JpaPermission;
import com.bzyd.jpa.entity.JpaUser;
import com.bzyd.jpa.vo.JpaUserQueryVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 用户分页查询动态条件构造器
 */
public class JpaUserSpecification implements Specification<JpaUser> {

    private JpaUserQueryVO param;//查询参数

    public JpaUserSpecification(JpaUserQueryVO param) {
        this.param = param;
    }

    @Override
    public Predicate toPredicate(Root<JpaUser> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
        List<Predicate> predicateList = new ArrayList<>();

        //通过角色名查询
        if (StringUtils.isNotBlank(param.getRoleName())) {
            Join<JpaPermission, JpaUser> join = root.join("role", JoinType.LEFT);//用户表左连接角色表
            Predicate predicate = criteriaBuilder.equal(join.get("roleName").as(String.class), param.getRoleName());
            predicateList.add(predicate);
        }

        //通过权限名称查询
        /**
         * 跨表查询，3个表
         * 需要通过权限名称查出对应的用户，JpaUser.role.permission = param.getPermissionName()
         * jointype.LEFT主要是说"role"这个属性是在哪个表中，这里是在JpaUser中。
         * 此处debug就可以发现，执行第一行之后，join中的Model就变成了JpaRole。(图贴在后面)
         * 此处是要通过权限名称查出对应的用户。所以先root.join("role", JoinType.LEFT)拿到JpaRole，然后再join.get("permission")拿到JpaPermission ，然后再匹配它的属性permissionName
         * 这里就是get出相应的属性，一直到你得到想要的属性为止。
         */
        if (StringUtils.isNotBlank(param.getPermissionName())) {
            Join<JpaPermission, JpaUser> join = root.join("role", JoinType.LEFT);
            Predicate predicate = criteriaBuilder.equal(join.get("permission").get("permissionName").as(String.class), param.getPermissionName());
            predicateList.add(predicate);
        }

        //in查询
        if (StringUtils.isNotBlank(param.getIds())) {
            CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("id").as(Long.class));
            List<String> idList = Arrays.asList(param.getIds().split(","));
            idList.forEach(id -> in.value(Long.parseLong(id)));
            predicateList.add(criteriaBuilder.and(in));
        }

        //like查询
        if (StringUtils.isNotBlank(param.getUserName())) {
            Predicate predicate = criteriaBuilder.like(root.get("userName").as(String.class), "%" + param.getUserName() + "%");
            predicateList.add(predicate);
        }

        //全等查询
        if (StringUtils.isNotBlank(param.getNickName())) {
            Predicate predicate = criteriaBuilder.equal(root.get("nickName").as(String.class), param.getNickName());
            predicateList.add(predicate);
        }

        //大于小于
        if (param.getAge() != null) {
            Predicate p1 = criteriaBuilder.le(root.get("age").as(Integer.class), param.getAge());//小于等于
            predicateList.add(p1);
            Predicate p2 = criteriaBuilder.gt(root.get("age").as(Integer.class), param.getAge() - 10);//大于
            predicateList.add(p2);
        }

        return predicateList.isEmpty() ? criteriaBuilder.conjunction() : criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
    }
}
